import axios from 'axios'
import { HttpExceptionTypeEnum, HttpRequestTypeEnum, } from '@/common/enum/enum_mediator.ts'
import { type ComponentCustomProperties } from '@vue/runtime-core'

// Axios 操作者
export class AxiosOperator {
    //region # 字段及构造器

    // 应用程序全局属性
    private appGlobalProperties:ComponentCustomProperties

    // 根目录
    private baseUrl:string

    // 默认配置
    // eslint-disable-next-line
    private defaultConfig:any

    /**
     * 有参构造器
     * @param appGlobalProperties
     * @param baseUrl - 根目录
     * */
    constructor(appGlobalProperties:ComponentCustomProperties, baseUrl:string) {
        this.baseUrl = baseUrl
        this.appGlobalProperties = appGlobalProperties

        this.init()
    }

    //endregion

    //region # 方法

    // Public

    /**
     * Get 请求
     * @param url 请求地址
     * @param data 请求数据
     * @param customErrorMessage 自定义错误消息
     * */
    public async get<TI, TO>(url:string, data:TI, customErrorMessage:string = ''):Promise<TO> {
        return await this.request(HttpRequestTypeEnum.get, url, data, customErrorMessage)
    }

    /**
     * Post 请求
     * @param url 请求地址
     * @param data 请求数据
     * @param customErrorMessage 自定义错误消息
     * */
    public async post<TI, TO>(url:string, data:TI, customErrorMessage:string = ''):Promise<TO> {
        return await this.request(HttpRequestTypeEnum.post, url, data, customErrorMessage)
    }

    // Private

    /**
     * 初始化
     * */
    private init():void {
        // eslint-disable-next-line
        const that = this

        // 设置默认配置
        this.defaultConfig = {
            // Host地址
            baseURL: '',
            // Api地址
            url: '',
            // 请求头
            headers: {
                'Content-Type': 'application/json;charset=utf-8',
            },
            // 请求数据
            data: {},
            // 请求超时的毫秒数
            timeout: 0,
            // `auth` 表示应该使用 HTTP 基础验证，并提供凭据
            // 这将设置一个 `Authorization` 头，覆写掉现有的任意使用 `headers` 设置的自定义 `Authorization`头
            // auth: {
            //     username: 'janedoe',
            //     password: 's00pers3cret'
            // },
            // 服务器响应的数据类型 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream'
            responseType: 'json',
            // 定义代理服务器
            // proxy: {
            //     host: '127.0.0.1',
            //     port: 9000,
            //     auth: {
            //         username: 'admin',
            //         password: 'admin'
            //     }
            // },
        }

        // 添加请求拦截器
        axios.interceptors.request.use(
            function(config) {
                // 在发送请求之前做些什么
                return config
            },
            function(error) {
                // 对请求错误做些什么
                return Promise.reject(error)
            },
        )

        // 添加响应拦截器
        axios.interceptors.response.use(
            // 处理请求成功
            // eslint-disable-next-line
            function(response:any) {
                return response.data ? response.data : response
            },
            // 异常处理
            // eslint-disable-next-line
            function(error:any) {
                return that.ResponseExceptionHandle(error)
            },
        )
    }

    /**
     * 请求
     * @param method 请求方式
     * @param url 请求地址
     * @param data 请求数据
     * @param customErrorMessage 自定义错误消息
     * */
    private async request<TI, TO>(method:HttpRequestTypeEnum, url:string, data:TI, customErrorMessage:string = '',):Promise<TO> {
        // 拼接完整地址
        const fullUrl = this.baseUrl + url

        // 设置请求头
        const headers = Object.assign(this.defaultConfig.headers, {})

        // 获取请求方式字符串
        const methodStr = this.appGlobalProperties.$enumConverts.httpRequestTypeConvert(method)

        // 设置配置项
        const config = Object.assign(this.defaultConfig, {
            // 请求地址
            url: fullUrl,
            // 请求方法
            method: methodStr,
            // 请求头
            headers,
            // 请求数据
            data: method == HttpRequestTypeEnum.get ? {} : data,
            params: method == HttpRequestTypeEnum.get ? data : {},
            // 自定义错误消息
            customErrorMessage,
        })

        // 执行请求
        const result:TO = await axios.request(config)
        return result
    }

    /**
     * 响应异常处理
     * @param error 异常
     * */
    // eslint-disable-next-line
    private ResponseExceptionHandle(error:any) {

        // 实例化 处理异常种类
        let errorMessage:string = ''

        // 设置异常消息
        if (error.response) {
            switch (error.response.status) {
                // 错误请求
                case 400:
                case 403:
                case 404:
                    errorMessage = this.appGlobalProperties.$enumConverts.httpExceptionTypeConvert(HttpExceptionTypeEnum.badRequest)
                    break
                // 身份失效
                case 401:
                    errorMessage = this.appGlobalProperties.$enumConverts.httpExceptionTypeConvert(HttpExceptionTypeEnum.noPermission)
                    break
                // 请求超时
                case 408:
                    errorMessage = this.appGlobalProperties.$enumConverts.httpExceptionTypeConvert(HttpExceptionTypeEnum.timeOut)
                    break
                // 服务器错误
                case 500:
                    errorMessage = error.response.data ? error.response.data : this.appGlobalProperties.$enumConverts.httpExceptionTypeConvert(HttpExceptionTypeEnum.serviceException)
                    break
                // 其他错误
                default:
                    errorMessage = error.response.data ? error.response.data : this.appGlobalProperties.$enumConverts.httpExceptionTypeConvert(HttpExceptionTypeEnum.requestFailed)
                    break
            }
        }
        else {
            errorMessage = this.appGlobalProperties.$enumConverts.httpExceptionTypeConvert(HttpExceptionTypeEnum.requestFailed)
        }

        // 设置异常消息
        const customErrorMessage:string =
            error.response && error.response.config.customErrorMessage
                ? error.response.config.customErrorMessage
                : ''
        errorMessage = customErrorMessage != '' ? customErrorMessage : errorMessage

        // 打印日志
        console.log('[RequestError]：', errorMessage)
        console.log('RequestUrl:', `${error.response.request.responseURL}`)
        console.log('RequestMethod:', error.config.method)
        console.log('RequestKey:', '')
        console.log('RequestData:', error.config.data)
        console.log('RequestSettings:', error.config)
        console.log('ResponseStatus:', error.response.status)
        console.log('ResponseData:', error.response.data)
        console.log('--------')

        console.log(error)

        this.appGlobalProperties.$service.toast.error(errorMessage);

        // 终端当前 promise链
        return new Promise(() => {
        })
    }


    //endregion
}
